package com.free.mini.gateway.utils.encryption;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import com.free.mini.gateway.config.ApiKeysConfig;

import lombok.extern.slf4j.Slf4j;

/**
 * @Description: AES加解密
 * @Author: zxh
 * @CreateDate: 2019/12/12 11:56
 */
@Slf4j
public class AES {
    private static volatile AES mHttpAes; // 接口请求加密
    private final static String KEY = "02b67a1b4e1eb86b571c586824e10f6c"; //配置key
    private final static String WAY = "AES/CBC/PKCS5Padding";
    private final SecretKeySpec secretKeySpec;
    private Cipher mCipherEncrypt, mCipherDecrypt;

    public AES(String key) {
        // 这里的 key 不可以使用 KeyGenerator、SecureRandom、SecretKey 生成
        byte[] raw = ByteConvertor.hexStringToBytes(key);
        // 指定加密的算法、工作模式和填充方式
        secretKeySpec = new SecretKeySpec(raw, "AES");
        try {
            mCipherEncrypt = Cipher.getInstance(WAY);
            mCipherDecrypt = Cipher.getInstance(WAY);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        }
    }

    private static AES getHttpAes() {
        if (mHttpAes == null) {
            synchronized (AES.class) {
                if (mHttpAes == null) {
                    mHttpAes = new AES(KEY);
                }
            }
        }
        return mHttpAes;
    }
    private String encryptAES(String content, boolean needUrlEncoder) {
        byte[] encryptedBytes = new byte[0];
        try {
            byte[] byteContent = content.getBytes(StandardCharsets.UTF_8);
            mCipherEncrypt.init(Cipher.ENCRYPT_MODE, secretKeySpec);
            encryptedBytes = mCipherEncrypt.doFinal(byteContent);

        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }
        StringBuilder sb = new StringBuilder();
        for (byte b : encryptedBytes) {
            sb.append(b);
        }
        log.debug("Aes加密后： " + sb);
        String finalData = AndroidBase64Utils.encode(encryptedBytes);//此处使用BASE64做转码功能
        if (needUrlEncoder) {
            finalData = URLEncoder.encode(finalData, StandardCharsets.UTF_8);//urlencoder
        }
        // 同样对加密后数据进行 base64 编码
        return finalData;
    }

    public String decryptAES(String content, boolean needUrlDecoder) {
        String urlDecoder = content;
        if (needUrlDecoder) {
            urlDecoder = URLDecoder.decode(content, StandardCharsets.UTF_8);
        }
        // base64 解码
        byte[] encryptedBytes = AndroidBase64Utils.decode(urlDecoder);
        byte[] result = new byte[0];
        try {
            mCipherDecrypt.init(Cipher.DECRYPT_MODE, secretKeySpec);
            result = mCipherDecrypt.doFinal(encryptedBytes);
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }
        String re = new String(result, StandardCharsets.UTF_8);
        return re;
    }

    public static String encryptHttp(String content, boolean needUrlEncoder) { //加密接口数据
        return getHttpAes().encryptAES(content, needUrlEncoder);
    }

    public static String decryptAES(String content, boolean needUrlDecoder, ApiKeysConfig apiKeysConfig) {
        String key = apiKeysConfig.getApiKey();
        byte[] raw = ByteConvertor.hexStringToBytes(key);
        // 指定加密的算法、工作模式和填充方式
        SecretKeySpec secretKeySpec = new SecretKeySpec(raw, "AES");
        Cipher mCipherDecrypt = null;
        try {
            mCipherDecrypt = Cipher.getInstance("AES/CBC/PKCS5Padding");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        }
        String urlDecoder = content;
        if (needUrlDecoder) {
            urlDecoder = URLDecoder.decode(content, StandardCharsets.UTF_8);
        }
        // base64 解码
        byte[] encryptedBytes = AndroidBase64Utils.decode(urlDecoder);
        byte[] result = new byte[0];
        try {
            mCipherDecrypt.init(Cipher.DECRYPT_MODE, secretKeySpec);
            result = mCipherDecrypt.doFinal(encryptedBytes);
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }
        String re = new String(result, StandardCharsets.UTF_8);
        return re;
    }

    public static String encryptAES(String content, boolean needUrlEncoder,ApiKeysConfig apiKeysConfig) {
        String key = apiKeysConfig.getApiKey();
        byte[] raw = ByteConvertor.hexStringToBytes(key);
        // 指定加密的算法、工作模式和填充方式
        SecretKeySpec secretKeySpec = new SecretKeySpec(raw, "AES");
        Cipher mCipherEncrypt = null;
        try {
            mCipherEncrypt = Cipher.getInstance("AES/CBC/PKCS5Padding");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        }
        byte[] encryptedBytes = new byte[0];
        try {
            byte[] byteContent = content.getBytes(StandardCharsets.UTF_8);
            mCipherEncrypt.init(Cipher.ENCRYPT_MODE, secretKeySpec);
            encryptedBytes = mCipherEncrypt.doFinal(byteContent);

        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }

        StringBuilder sb = new StringBuilder();
        for (byte b : encryptedBytes) {
            sb.append(b);
        }
        log.debug("Aes加密后： " + sb);

        String finalData = AndroidBase64Utils.encode(encryptedBytes);//此处使用BASE64做转码功能
        if (needUrlEncoder) {
            finalData = URLEncoder.encode(finalData, StandardCharsets.UTF_8);//urlencoder
        }
        // 同样对加密后数据进行 base64 编码
        return finalData;
    }
}
